package db

import (
	"AQChain/models"
	"fmt"
	"github.com/astaxie/beego/orm"
	"log"
)

func ReadBlockByNumber(number int64) *models.Block {
	block := &models.Block{
		Number: number,
	}
	err := orm.NewOrm().Read(block)
	if err != nil {
		if err != orm.ErrNoRows {
			log.Println(err)
		}
		return nil
	}
	return block
}

func ReadBlockByHash(hash string) *models.Block {
	block := &models.Block{
		Hash: hash,
	}
	err := orm.NewOrm().Read(block)
	if err != nil {
		if err != orm.ErrNoRows {
			log.Println(err)
		}
		return nil
	}
	return block
}

func ReadLastBlock() *models.Block {
	block := &models.Block{}
	err := orm.NewOrm().Raw("select * from block where number = (select max(number) from block) ").QueryRow(block)
	if err != nil {
		if err != orm.ErrNoRows {
			log.Println(err)
		}
		return nil
	}
	return block
}

func ReadBlocks(from int64, len int64) []models.Block {
	var blocks []models.Block
	_, err := orm.NewOrm().QueryTable(&models.Block{}).Limit(len, from).All(&blocks)
	if err != nil {
		log.Println(err)
	}
	return blocks
}

func ReadBlocksByCreator(creator string) []*models.Block {
	var blocks []*models.Block
	_, err := orm.NewOrm().QueryTable(&models.Block{}).Filter("creator", creator).All(&blocks)
	if err != nil {
		log.Println(err)
		return nil
	}
	return blocks
}

// 保存新区块 重要！
func NewBlock(block models.Block) error {
	db := orm.NewOrm()

	// 异常处理 rollback
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("更新区块数据错误：", err)
			db.Rollback()
		}
	}()

	db.Begin()
	// 遍历区块交易
	for _, tx := range block.Txs {
		// 保存交易
		tx.BlockNumber = block.Number
		_, err := db.Insert(tx)
		if err != nil {
			panic(err)
		}
		// 交易类型判断
		switch tx.Type {
		case 0:
			// 上传
			// 获取Account数据 先查询是否存在Account 不存在新创建
			account := readAccount(db, tx.From)
			if account == nil {
				account = newAccount(db, tx.From)
			}
			// 更新file数据
			file := models.NewFile(account.Address, tx.Timestamp, tx.FileID)
			_, err = db.Insert(file)
			if err != nil {
				panic(err)
			}
			// 设置贡献值
			err = addContribution(db, tx.From, 1, 0)
			if err != nil {
				panic(err)
			}
		case 1:
			// 拥有者激活文件交易
			// 交易转换成文件交易记录
			transfer := models.TransferFromTx(tx)
			persistent := ReadTransfer(transfer.ID)
			if persistent != nil {
				_, err = db.Update(transfer, "owner_tx", "status")
				if err != nil {
					panic(err)
				}
			} else {
				_, err = db.Insert(transfer)
				if err != nil {
					panic(err)
				}
			}
			// 更新file.status
			err := updateStatus(db, tx.FileID, 1)
			if err != nil {
				panic(err)
			}
		case 2:
			// 购买者生成或修改交易申请
			// 交易转换成文件交易记录
			transfer := models.TransferFromTx(tx)
			persistent := ReadTransfer(transfer.ID)
			if persistent != nil {
				_, err = db.Update(transfer, "price", "buyer_tx", "status")
				if err != nil {
					panic(err)
				}
			} else {
				_, err = db.Insert(transfer)
				if err != nil {
					panic(err)
				}
			}
		case 3:
			// 拥有者拒绝交易申请
			transfer := models.TransferFromTx(tx)
			_, err = db.Update(transfer, "owner_tx", "status")
			if err != nil {
				panic(err)
			}
		case 4:
			// 拥有者确认交易
			transfer := models.TransferFromTx(tx)
			_, err = db.Update(transfer, "owner_tx", "status")
			if err != nil {
				panic(err)
			}
			// 更新file.status
			err := updateStatus(db, tx.FileID, 2)
			if err != nil {
				panic(err)
			}
		case 5:
			// 购买者再确认
			transfer := models.TransferFromTx(tx)
			_, err = db.Update(transfer, "buyer_tx", "status", "timestamp")
			if err != nil {
				panic(err)
			}
			// 更新之前拥有者激活的记录
			temp := &models.Transfer{
				Owner:  transfer.Owner,
				FileID: transfer.FileID,
			}
			temp.ID = temp.EncodeTransfer()
			temp.Status = 3
			_, err = db.Update(temp, "status")
			if err != nil {
				panic(err)
			}
			// 更新文件
			err = updateFile(db, transfer.FileID, transfer.Buyer, transfer.ID, transfer.Price)
			if err != nil {
				panic(err)
			}
			// 更新Account
			// 获取Account数据 先查询是否存在Account 不存在新创建
			account := readAccount(db, tx.From)
			if account == nil {
				account = newAccount(db, tx.From)
			}
			// 海绵函数(未完成)
			// 查找Buyer的上次交易记录
			record := ReadCompletedTransferByBuyer(db, transfer.Buyer)
			if record != nil {
			}
			// 设置贡献值
			err = addContribution(db, transfer.Buyer, 0, transfer.Price)
			if err != nil {
				panic(err)
			}
		case 6:
			// 购买者取消
			transfer := models.TransferFromTx(tx)
			_, err = db.Update(transfer, "buyer_tx", "status")
			if err != nil {
				panic(err)
			}
			// 更新file.status
			err := updateStatus(db, tx.FileID, 1)
			if err != nil {
				panic(err)
			}
		case 7:
			// 拥有者终止
			transfer := models.TransferFromTx(tx)
			persistent := ReadTransfer(transfer.ID)
			if persistent != nil {
				_, err = db.Update(transfer, "owner_tx", "status")
				if err != nil {
					panic(err)
				}
			} else {
				_, err = db.Insert(transfer)
				if err != nil {
					panic(err)
				}
			}
			// 更新之前拥有者激活的记录
			temp := &models.Transfer{
				Owner:  transfer.Owner,
				FileID: transfer.FileID,
			}
			temp.ID = temp.EncodeTransfer()
			temp.Status = 3
			_, err = db.Update(temp, "status")
			if err != nil {
				panic(err)
			}
			// 更新file.status
			err := updateStatus(db, tx.FileID, 0)
			if err != nil {
				panic(err)
			}
		}

		/*if tx.Type == 0 {
			// 账户数据更新
			account := readAccount(db, tx.Owner)
			if account == nil {
				account = newAccount(db, tx.Owner)
			}
			// 上传添加file表
			file:=models.NewFile(account.Address,tx.FileID)
			err = insertFile(db, file)
			if err != nil {
				panic(err)
			}
			err = addContribution(db, tx.Owner, 1, 0)
			if err != nil {
				panic(err)
			}
		} else {
			// 生成请求
			transfer := models.TransferFromTx(tx)
			// 判断交易状态
			switch tx.Status {
			case 0:
				// 创建交易请求
				err := InsertTransfer(db, transfer)
				if err != nil {
					panic(err)
				}
			case 1:
				// 确认交易请求
				err := UpdateTransferConfirm(db, transfer)
				if err != nil {
					panic(err)
				}
			case 2:
				// 完成交易请求
				err := UpdateTransferComplete(db, transfer)
				if err != nil {
					panic(err)
				}
				// 交易完成更新文件表
				err = updateFile(db, transfer.FileID, transfer.Owner, transfer.ID, transfer.Price)
				if err != nil {
					panic(err)
				}

				// 账户数据更新
				if readAccount(db, tx.Owner) == nil {
					newAccount(db, tx.Owner)
				}
				// 缺少海绵函数
				err = addContribution(db, tx.Owner, 0, 1)
				if err != nil {
					panic(err)
				}
			}
		}*/
	}
	// 保存区块
	_, err := db.Insert(&block)
	if err != nil {
		panic(err)
	}
	db.Commit()
	return nil
}

func GenesisBlock() models.Block {
	genesisBlock := ReadBlockByNumber(0)
	if genesisBlock == nil {
		// 加一个交易解决产生贡献值解决第一个区块生成问题 问题这个admin账户是否会影响？
		genesisBlock = &models.Block{
			Number:       0,
			Hash:         "genesisBlock",
			Creator:      "admin",
			PrevHash:     "",
			Timestamp:    "2006-01-02 15:04:05",
			MerkleRoot:   "",
			Transactions: models.Transactions{},
		}
		_ = NewBlock(*genesisBlock)
	}

	return *genesisBlock
}
